#ifndef DW_GRAFFITI_IMAGE_H
#	define DW_GRAFFITI_IMAGE_H

#include "enums.h"

#include "imagemanager.h"

namespace dw {
	namespace graffiti {

class Image
{
public : //! @name Construction & Destruction
	//! @{
	Image(const glm::ivec3 size, pixel::format::formats format, dw::uint bpp, dw::uint32 mipmapsCount, bool isCubeMap)
	:	m_size(size)
	,	m_format(format)
	,	m_bpp(bpp)
	,	m_mipmapsCount(mipmapsCount)
	,	m_isCubeMap(isCubeMap)
	{
		m_mipmaps = new Mipmap [m_mipmapsCount + 1];

		for (dw::uint32 mipmapIt = 0; mipmapIt < m_mipmapsCount + 1; ++mipmapIt)
		{
			m_mipmaps[mipmapIt].data = NULL;
			m_mipmaps[mipmapIt].size = 0;
		}
	}

	~Image()
	{
		for (dw::uint32 mipmapIt = 0; mipmapIt < m_mipmapsCount + 1; ++mipmapIt)
		{
			delete [] m_mipmaps[mipmapIt].data;
		}

		delete [] m_mipmaps;
	}
	//! @}

public : //! @name Commands
	//! @{
	const dw::byte* map(dw::uint mipmap) const
	{
		dwAssert(mipmap < m_mipmapsCount + 1, "Invalid parameter: mipmap is out of bounds");

		return m_mipmaps[mipmap].data;
	}

	dw::byte* map(dw::uint mipmap)
	{
		dwAssert(mipmap < m_mipmapsCount + 1, "Invalid parameter: mipmap is out of bounds");

		return m_mipmaps[mipmap].data;
	}

	void resize(dw::uint32 mipmap, dw::uint32 size)
	{
		dwAssert(mipmap < m_mipmapsCount + 1, "Invalid parameter: mipmap is out of bounds");

		if (m_mipmaps[mipmap].size != size)
		{
			delete [] m_mipmaps[mipmap].data;
		}

		m_mipmaps[mipmap].data = new dw::byte [size];
		m_mipmaps[mipmap].size = size;
	}

	void set(dw::uint32 mipmap, dw::byte* data, dw::uint32 size)
	{
		resize(mipmap, size);

		memcpy(m_mipmaps[mipmap].data, data, size);
	}
	//! @}

public : //! @name State
	//! @{
	const glm::ivec3& getSize() const { return m_size; }
	dw::uint32 getMipmapsCount() const { return m_mipmapsCount; }
	pixel::format::formats getPixelFormat() const { return m_format; }
	const dw::uint32 getMipmapSize(dw::uint mipmap) const
	{
		dwAssert(mipmap < m_mipmapsCount + 1, "Invalid parameter: mipmap is out of bounds");

		return m_mipmaps[mipmap].size;
	}
	bool isCompressed() const
	{
		return m_format == pixel::format::dxt1 ||
			m_format == pixel::format::dxt3 ||
			m_format == pixel::format::dxt5;
	}
	//! @}

private : //! @name Copy protection
	//! @{
	Image(const Image& ref);
	//! @}

private : //! @name Types definitions
	//! @{
	struct Mipmap
	{
		dw::byte* data;
		dw::uint32 size;
	};
	//! @}

private : //! @name Data
	//! @{
	glm::ivec3 m_size;
	pixel::format::formats m_format;
	dw::uint32 m_bpp;
	dw::uint32 m_mipmapsCount;
	bool m_isCubeMap;
	Mipmap* m_mipmaps;
	//! @}

};

	} // namespace graffiti
} // namespace dw

#endif // DW_GRAFFITI_IMAGE_H
